Part 15: Mitsuzen HDI-10 - Heart
Part 15 - Mitsuzen HDI-10 - Heart=== Trash World Inbox ===
GuavaMoment posted:
So first off you can get a 12 line, 10 activity solution with this by combining some tricks:Yeah, you create 807 exas, but it works! MODI -1 0 X kills the exa.code:
LINK 800 LINK 800 LINK 800 COPY 807 X MARK CLONE MODI -1 X X REPL CLONE LINK X MARK CASHGET2 COPY 20 #DISP DIVI 999 #CASH X JUMP CASHGET2
It's a bit weird to think about the modulo function with negative numbers but in this case it basically acts as a decrement operation that crashes at zero. I should remember that, it could come in handy later.
Moto42 posted:
So, yea, it is faster to start with 7 EXAs, but each one can only have 7 lines of code.
Quackles posted:
Here's my desultory best effort, with loop unrolling in a similar way:1146/50/10.code:
@REP 3 LINK 800 ;LES GO @END COPY 800 X MARK REPLICATE REPL GOLINK ADDI X 1 X TEST X < 806 TJMP REPLICATE MARK GOLINK LINK X MARK KICKOUT COPY 20 #DISP MODI #CASH 32 T TJMP KICKOUT MARK KICKTEN @REP 32 COPY 20 #DISP @END COPY #CASH T TJMP KICKTEN
GuavaMoment posted:
For getting things fast, you need lots of loop unrolling, so I populate the exas differently that doesn't need a killer. It's a tiny bit slower to do that task but saves a bunch of lines, making things overall faster. Why giant loops of 21 and 8? No idea, ask me years ago when I did this by trial and error until it worked. Why do I test for #CASH > 29 even at a time when I know it's not? No idea, but it's faster! 1102/50/10code:
LINK 800 LINK 800 LINK 800 COPY 806 X MARK CLONE REPL CASHGET SUBI X 1 X TEST X = 800 FJMP CLONE MARK CASHGET LINK X MARK SPILL @REP 21 COPY 20 #DISP @END MARK TENS @REP 8 COPY 20 #DISP @END TEST #CASH > 29 TJMP SPILL TEST #CASH > 8 TJMP TENS MARK CASHGET2 COPY 20 #DISP DIVI 999 #CASH X JUMP CASHGET2
Alright, so GuavaMoment's 1102 cycle solution is the best we got in the threads. But that's still a ways from the 1072 top percentile, and I got curious. So I decided to look it up. Turns out someone called StinkingBanana uploaded a fast solution just last week. Since they also uploaded a lot of stuff about future puzzles I won't directly link to it here. But I will share the solution because it's a thing of beauty.
Spoilered for anyone who wants to give it a try themselves first.
After getting the clones in place, simply do:
MARK DISP
@REP {as often as possible}
MODI 20 #CASH #DISP
COPY 20 #DISP
@END
JUMP DISP
You see what this does? The MODI/COPY combination handles the checking if we're done without any conditional jumping at all.
- If #CASH > 20, MODI 20 #CASH #DISP will write 20 to #DISP, acting like a free, additional COPY.
- If it's between 0 and 20, it will write 0 to #DISP, which doesn't do anything. At this point only the actual COPY instructions work.
- If #CASH is exactly 0, the next MODI will immediately crash the EXA.
So, for the majority of the program, MODI will act like an additional COPY. For the last 20 bills, it'll act like a "Am I done?" check.
Their solution runs at 1072/50/10, but has a bit of slack in the cloning code. Combining it with GuavaMoment's cloning code drops it to 1069, and using my solution with the CLEANUP clone, I managed to get it down all the way to 1067 cycles.
=== Mitsuzen HDI-10 - Heart ===
Well, that caused a bit of chaos.
But not as much as I hoped.
I wonder why.
I got one vote for each option. This one goes to the random number generator.
People are good at ignoring problems.
Hmm.
I'll have to aim for something bigger next time.
...Uh oh.
They're not lying, though. There are computers everywhere. In fact, there's probably a computer near you, right now!
Damn, the phage is getting to my heart. Gotta do something quick.
So you're going to be hacking your own heart.
Two votes for the third option.
I'm a little scared.
Why?
What happens if your heart stops beating?
Don't tell me. You die?
Processing.
Huh. I guess that explains some things.
At least all you need to do is make it beat.
It's, uh, it's a little more complicated than that, Ember. I thought you studied humans, how do you not know our basic biology?
Human physiology is fascinating.
I should learn more about it.
...Why do I feel like I just said the wrong thing?
Either way, let's get started.
OST: EXA Power
It's been a while since I last hacked my body, let's see if I remember how this works.
I have to do the following:
- Read a value from the nerve connected to your central nervous system (CNS) and make your heart beat by writing a sequence of values to your sinoatrial (SA-N) and atrioventricular (AV-N) nodes as indicated in the HDI-10 I/O log when holding the "SHOW GOAL" button. The length of each sequence of values should be equal to the value from the CNS divided by -10. Repeat ad infinitum.
- It is not necessary to leave no trave. Your EXAs should be written to operate indefinitely.
- For more information see "Debugging the Phage" in the first issue of the zine.
I've shown that article from the zine already, nothing new there. I have to write values like this:
Alright, if I understand correctly, when I get -42 as input, I have to write -42 / -10 = 4 (rounded down) values to the outputs. The first value to SA-N has to be 40, the others are -70 (neural resting potential, according to the zine). For the AV-N output the first value has to be -70, the SECOND 40, and the rest -70.
Note that EXA cycles are much faster than a heartbeat, so I don't have to sync cycles perfectly, as long as I get the order of outputs right.
code:
LINK 800
REPL SA
REPL AV
HALT
MARK SA
LINK 1
LINK 1
HALT
MARK AV
LINK 3
LINK 3
For the lowest activity score I also can't move the EXAs around any further so I'll have to use the M register, and since both EXAs need to know how many cycles to write, I'll need to send the value to M twice. So the input EXA will have to be something like this:
code:
LINK 800
REPL SA
REPL AV
MARK INLOOP
DIVI #NERV -10 X
COPY X M
COPY X M
JUMP INLOOP
Both of the other EXAs have to read from M and write the values to their nerve connections:
code:
MARK SA
LINK 1
LINK 1
MARK SALOOP
SUBI M 1 T
COPY 40 #NERV
MARK SACOUNTDOWN
COPY -70 #NERV
SUBI T 1 T
TJMP SACOUNTDOWN
JUMP SALOOP
MARK AV
LINK 3
LINK 3
MARK AVLOOP
SUBI M 2 T
COPY -70 #NERV
COPY 40 #NERV
MARK AVCOUNTDOWN
COPY -70 #NERV
SUBI T 1 T
TJMP AVCOUNTDOWN
JUMP AVLOOP
Let's test this code.
Oh... the first 17 tests succeeded but after that, "operation successful, patient dead" as they say? There's some wrong outputs in the list (and the cycle count keeps going until I abort since the EXAs never quit). What went wrong here?
Stepping through the code a bit, it turns out that the AV EXA is a bit faster than the SA one. Normally that's no problem, but since this test has several fast heartbeats (inputs between -30 and -39), at some point the AV EXA reads from the M register twice before SA has a chance, desyncing everything.
One way to fix that would be to have the input EXA only send to ONE of the others and have that one contact the other one. Serial messaging. That feels slow. I have a better idea.
The AV EXA does 2 writes before getting into the loop, the SA one only 1. That's why AV is faster. I'm going to try having the SA EXA also write two values before getting into the loop. This would fail if the input is ever between -29 and -20... but the AV EXA already can't handle that, so let's try it and hope for the best.
Aaaaand.... it works! 88/32/5.
Top percentiles are 80, 24, and 5. For the Phage levels, while the EXAs should run forever, the cycle count is based on how long it takes to fill out the test result table to the right.
For speeding it up, I tried some loop unrolls first.
code:
@REP 4
COPY -70 #NERV
SUBI T 1 T
FJMP SALOOP
@END
Let's try something completely different. Can we parallellize? Well, not really with the M register. But we can have a lot of EXAs running around at the same time.
I tried some things the fact that the amount of time the EXAs are busy writing depends on the input caused me issues. If you send EXAs to the output nerves as fast as possible, the second EXA will start writing before the first is done. That won't work. We need to slow them down - but not too much. Perhaps the output EXA could signal when it's done? But that would be through the M register which is always a bit slow - taking 2 cycles at the least.
I came up with this instead.
code:
;XA
LINK 800
MARK NEXT
DIVI #NERV -10 X
SUBI X 3 T
REPL SA
REPL AV
JUMP NEXT
MARK SA
LINK 1
LINK 1
COPY 40 #NERV
COPY -70 #NERV
JUMP COUNTDOWN
MARK AV
LINK 3
LINK 3
COPY -70 #NERV
COPY 40 #NERV
MARK COUNTDOWN
@REP 5
COPY -70 #NERV
MODI -1 T T
@END
JUMP COUNTDOWN
;XB
LINK 800
REPL AV
REPL WAIT
LINK 1
REPL WAIT
REPL WAIT
REPL WAIT
LINK 1
REPL WAIT
MARK WAIT
JUMP WAIT
MARK AV
LINK 3
REPL WAIT
REPL WAIT
REPL WAIT
LINK 3
REPL WAIT
JUMP WAIT
I needed to keep one XB in the input host as well, because otherwise there's some issues with the wrong XA clone LINKing first. This way, only one clone can be formed at a time.
Since each XA clone can die after doing its thing, this means I can consolidate the countdowns into a single loop, which can be unrolled quite a few times. And I use the MODI trick GuavaMoment showed us in the Trash World Inbox to decrement-or-die in a single cycle.
And this gets me a score way below the top percentile, with only 69 cycles. Nice!
To my surprise, when I looked at my stats after this, it listed my lowest size as 25. How did I do that?
Turns out it was actually the parallel-but-wait-for-M solution I mentioned being too slow. It's this code:
code:
LINK 800
MARK NEXT
DIVI #NERV -10 X
SUBI X 2 T
REPL SA
REPL AV
VOID M
VOID M
JUMP NEXT
MARK SA
LINK 1
LINK 1
COPY 40 #NERV
COPY -70 #NERV
JUMP COUNTDOWN
MARK AV
LINK 3
LINK 3
COPY -70 #NERV
COPY 40 #NERV
MARK COUNTDOWN
COPY -70 #NERV
SUBI T 1 T
TJMP COUNTDOWN
COPY 0 M
Do you ever wish you were a computer?
A functioning computer, I mean.
Well, do we, thread?
And for next time...
Well, this is flattering.
Someone found a bunch of my network nodes and sent in a tip to Ghast!
Too bad I can't have people knowing about me.
You're going to have to hack me out of that message.
And that's the two votes for this week.